﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using Core.Models;
using System.Text;

namespace Core.Controllers
{
    public class FileController : Controller
    {
        //
        // GET: /File/

        [Authorize]
        public ActionResult Index(Guid id)
        {
            Guid BUId = id;
            CoreEntities core = new CoreEntities();
            List<TagCategory> tclist = core.TagCategories.Where(m => (m.TagCategoryName == "File" && (m.BusinessUnitId == null || m.BusinessUnitId == id))).ToList();
            if (tclist.Count <= 0) return RedirectToAction("NeedFileTags");
            Guid TagCategoryId = tclist[0].TagCategoryId;
            List<Tag> tlist = core.Tags.Where(m => m.TagCategoryId == TagCategoryId).ToList();
            if (tlist.Count <= 0) return RedirectToAction("NeedFileTags");
            ViewBag.BusinessUnitId = BUId;
            ViewBag.BusinessUnitName = core.BusinessUnits.First(m => m.BusinessUnitId == BUId).BusinessUnitName;
            return View();
        }

        //
        // GET: /File/NeedFileTags

        public ActionResult NeedFileTags()
        {
            return View();
        }

        //
        // GET: /File/Upload

        [Authorize]
        public ActionResult Upload(Guid id)
        {
            CoreEntities core = new CoreEntities();
            List<TagCategory> tclist = core.TagCategories.Where(m => (m.TagCategoryName == "File" && (m.BusinessUnitId == null || m.BusinessUnitId == id))).ToList();
            if (tclist.Count <= 0) return RedirectToAction("NeedFileTags");
            Guid TagCategoryId = tclist[0].TagCategoryId;
            List<Tag> tlist = core.Tags.Where(m => m.TagCategoryId == TagCategoryId).ToList();
            if (tlist.Count <= 0) return RedirectToAction("NeedFileTags");
            ViewBag.BusinessUnitId = id;
            ViewBag.BusinessUnitName = core.BusinessUnits.First(m => m.BusinessUnitId == id).BusinessUnitName;
            ViewBag.TagCategoryId = TagCategoryId;
            return View();
        }

        [HttpPost]
        public JsonResult Tags(string search, int maxitems, Guid TagCategoryId)
        {
            CoreEntities core = new CoreEntities();
            List<Tag> tlist = core.Tags.Where(m => (m.TagCategoryId == TagCategoryId && m.TagName.StartsWith(search))).ToList();
            List<NameId> data = new List<NameId>();
            foreach (Tag tag in tlist)
            {
                NameId item = new NameId();
                item.Name = tag.TagName;
                item.Id = tag.TagId.ToString();
                data.Add(item);
            }
            return Json(data);
        }

        /// <summary>
        /// Upload a file and return a JSON result
        /// </summary>
        /// <param name="file">The file to upload.</param>
        /// <returns>a FileUploadJsonResult</returns>
        /// <remarks>
        /// It is not possible to upload files using the browser's XMLHttpRequest
        /// object. So the jQuery Form Plugin uses a hidden iframe element. For a
        /// JSON response, a ContentType of application/json will cause bad browser
        /// behavior so the content-type must be text/html. Browsers can behave badly
        /// if you return JSON with ContentType of text/html. So you must surround
        /// the JSON in textarea tags. All this is handled nicely in the browser
        /// by the jQuery Form Plugin. But we need to overide the default behavior
        /// of the JsonResult class in order to achieve the desired result.
        /// </remarks>
        /// <seealso cref="http://malsup.com/jquery/form/#code-samples"/>
        [Authorize]
        public FileUploadJsonResult AjaxUpload(HttpPostedFileBase file)
        {
            if (file.ContentLength <= 524288)
            {
                CoreEntities core = new CoreEntities();
                Guid BUId = new Guid(Request.Form["hdnBusinessUnitId"].ToString());
                Guid DomainId = core.BusinessUnits.First(m => m.BusinessUnitId == BUId).DomainId;
                Core.Models.File f = new Models.File();
                f.FileId = Guid.NewGuid();
                f.DomainId = DomainId;
                f.BusinessUnitId = BUId;
                f.Description = Request.Form["txtDescription"].ToString();
                f.Filename = (file.FileName.LastIndexOf('\\') > 0) ? file.FileName.Substring(file.FileName.LastIndexOf('\\')+1) : file.FileName;
                f.Extension = file.FileName.Substring(file.FileName.IndexOf("."));
                f.Size = file.ContentLength;
                byte[] buffer = new byte[f.Size];
                int bytesread = file.InputStream.Read(buffer, 0, f.Size);
                f.Data = buffer;
                f.IsPublicYN = "Y";
                f.CreateDT = DateTime.Now;
                f.CreatedById = (Guid)Session["UserId"];
                f.CreatedByName = Session["UserFullName"].ToString();
                f.LastAccessedDT = DateTime.Now;
                core.AddToFiles(f);
                List<string> tagids = Request.Form["TagIds"].ToString().Split((",").ToCharArray(), 9999).ToList();
                foreach (string tagid in tagids)
                {
                    if(!String.IsNullOrEmpty(tagid))
                    {
                        Guid TagId = new Guid(tagid);
                        Tag tag = core.Tags.First(m => m.TagId == TagId);
                        f.Tags.Add(tag);
                    }
                }
                core.SaveChanges();

                // Return JSON
                return new FileUploadJsonResult { Data = new { message = string.Format("{0} uploaded successfully.", System.IO.Path.GetFileName(file.FileName)) } };
            }
            else
            {
                return new FileUploadJsonResult { Data = new { message = "Error, File is too large." } };
            }
        }

        public ActionResult Download(Guid id)
        {
            CoreEntities core = new CoreEntities();
            List<Core.Models.File> files = core.Files.Where(m => m.FileId == id).ToList();
            if (files.Count > 0)
            {
                Response.Clear();
                Response.AddHeader("Content-Disposition", "attachment; filename=" + files[0].Filename);
                Response.ContentType = "application/octet-stream";                
                Response.BinaryWrite(files[0].Data);
                Response.Flush();
                Response.End();
            }
            return new EmptyResult();
        }

        private static byte[] ReadFile(string path)
        {
            try
            {
                // Open the image file
                using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    // Create an array of bytes
                    byte[] bData = new byte[fs.Length];
    
                    // Read the image file
                    fs.Read(bData, 0, Convert.ToInt32(fs.Length));

                    return bData;
                }
            }
            catch
            {  
            }
            return null; 
        }

        //
        // GET: /File/Delete/5

        [Authorize]
        public ActionResult Delete(Guid id)
        {
            CoreEntities core = new CoreEntities();
            Core.Models.File file = core.Files.First(m => m.FileId == id);
            return View(file);
        }

        //
        // POST: /File/Delete/5

        [HttpPost]
        [Authorize]
        public ActionResult Delete(Guid FileId, Guid BusinessUnitId, FormCollection collection)
        {
            try
            {
                // TODO: Add delete logic here
                CoreEntities core = new CoreEntities();
                List<Tag> tags = core.Files.First(m => m.FileId == FileId).Tags.ToList();
                foreach (Tag tag in tags)
                {
                    core.Files.First(m => m.FileId == FileId).Tags.Remove(tag);
                }
                core.Files.DeleteObject(core.Files.First(m => m.FileId == FileId));
                core.SaveChanges();
                return RedirectToAction("Index", new { id = BusinessUnitId});
            }
            catch
            {
                return View();
            }
        }

        [HttpPost]
        [Authorize]
        public JsonResult ListData(FormCollection collection)
        {
            CoreEntities core = new CoreEntities();
            Guid BUId = new Guid(collection.GetValues("BusinessUnitId")[0].ToString());
            int SkipRecs = int.Parse(collection.GetValues("iDisplayStart")[0].ToString());
            int TakeCount = int.Parse(collection.GetValues("iDisplayLength")[0].ToString());
            string strSearch = collection.GetValues("sSearch")[0].ToString();
            DataTableResponse r = new DataTableResponse();
            var q = (from f in core.Files
                    where (f.BusinessUnitId == BUId && f.IsPublicYN == "Y" && (f.Description.Contains(strSearch) || f.Filename.Contains(strSearch)))
                    orderby (f.Filename)                    
                    select new
                    {
                        f.FileId,
                        f.DomainId,
                        f.BusinessUnitId,
                        f.Description,
                        f.Filename,
                        f.Size,
                        f.LastAccessedDT
                    })
                    .Skip(SkipRecs).Take(TakeCount).ToList();
            r.sEcho = collection.GetValues("sEcho")[0].ToString();
            r.iTotalRecords = core.Files.Where(m => (m.BusinessUnitId == BUId && m.IsPublicYN == "Y" && (m.Description.Contains(strSearch) || m.Filename.Contains(strSearch)))).Count();
            r.iTotalDisplayRecords = r.iTotalRecords;
            foreach (var file in q)
            {
                List<string> r1 = new List<string>();
                string deleteurl = String.Format("<a href=\"/{0}/{1}/{2}\" id=\"deletelink\" title=\"{1}\" />", "File", "Delete", file.FileId.ToString());
                r1.Add(deleteurl);
                r1.Add(file.Description);
                r1.Add(String.Format("<a href=\"/File/Download/{0}\">{1}</a>",file.FileId.ToString(), file.Filename));
                r1.Add(Tags(file.FileId, core));
                r1.Add(Core.Tools.FileSize(file.Size));
                r1.Add(String.Format("{0:g}", file.LastAccessedDT));
                r.aaData.Add(r1);
            }
            return Json(r);
        }

        private string Tags(Guid FileId, CoreEntities core)
        {
            List<Tag> tags = core.Files.First(m => m.FileId == FileId).Tags.ToList();
            StringBuilder sb = new StringBuilder("");
            foreach (Tag tag in tags)
            {
                sb.Append(", " + tag.TagName);
            }
            return sb.Length > 2 ? sb.ToString().Substring(2) : "";
        }
    }
}
